/*
	Programação Concorrente
	Trabalho 1
	Turma A
	
	Adilson Rapozo
	Luiz Bertoni
	Rodrigo Costa
*/

#include <stdio.h>
#include <gmp.h>
#include <time.h>

#define PRECISION 33219281
#define PRECISION_FOR_TEST 1024

void calculatePi ( mpf_t pi , mpf_t a , mpf_t b , mpf_t t , mpf_t fourT ) {

	static int i = 1 ;
	FILE * file , file2 ;

	mpf_add ( pi , a , b ) ;
	mpf_pow_ui ( pi , pi , 2 ) ;
	mpf_mul_ui ( fourT , t , 4 ) ;
	mpf_div ( pi , pi , fourT ) ;

	/* saving result */

	file = savePI( "gl" , pi, i ) ;
	file2 = fopen ( REAL_PI , "rw" ) ;

	printf ( "iteracao %d, %lu digitos corretos\n" , i , compare( file , file2 ) ) ;

	fclose ( file ) ;
	fclose ( file2 ) ;
}

int main ( void ) {

	/* initialization */

	clock_t start,end;

	int i;

	mpf_t a ;
	mpf_t prevA ;

	mpf_t b ;

	mpf_t t ;
	mpf_t prevT ;
	mpf_t fourT ;

	mpf_t p ;

	mpf_t sqrtTwo ;

	mpf_t pi ;

	mpf_set_default_prec ( PRECISION_FOR_TEST ) ;

	mpf_init ( a ) ;
	mpf_init ( prevA ) ;

	mpf_init ( b ) ;

	mpf_init ( t ) ;
	mpf_init ( prevT ) ;
	mpf_init ( fourT ) ;

	mpf_init ( p ) ;

	mpf_init ( sqrtTwo ) ;

	mpf_init ( pi ) ;

	/* initial values */

	start = clock();

	mpf_set_str ( a , "1e0" , 10 ) ;
	mpf_set_str ( t , "0.25e0" , 10 ) ;
	mpf_set_str ( p , "1e0" , 10 ) ;

	mpf_sqrt_ui ( sqrtTwo , 2 ) ;
	mpf_ui_div ( b , 1 , sqrtTwo ) ;

	/* itarations */

	do {

		mpf_set ( prevA , a ) ;
		mpf_add ( a , prevA , b ) ;
		mpf_div_ui ( a , a , 2 ) ;

		mpf_mul ( b , b , prevA ) ;
		mpf_sqrt ( b , b ) ;

		mpf_set ( prevT , t ) ;
		mpf_sub ( t , prevA , a ) ;
		mpf_pow_ui ( t , t , 2 ) ;
		mpf_mul ( t , t , p ) ;
		mpf_sub ( t , prevT , t ) ;
		
		mpf_mul_ui ( p , p , 2 ) ;

		calculatePi ( pi , a , b , t , fourT ) ;

	} while ( mpf_cmp ( a , b ) != 0 ) ;

	end = clock();

	printf("Executed in %.2lf seconds.\n",((double)(end-start))/CLOCKS_PER_SEC);

	/* termination */

	mpf_clear ( a ) ;
	mpf_clear ( prevA ) ;

	mpf_clear ( b ) ;

	mpf_clear ( t ) ;
	mpf_clear ( prevT ) ;
	mpf_clear ( fourT ) ;

	mpf_clear ( p ) ;

	mpf_clear ( sqrtTwo ) ;

	mpf_clear ( pi ) ;

	return 0 ;
}

